package com.example.springboottest.example.thread;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.TimeUnit;

public class ThreadWaitTest<E> {
    private Queue<E> queue = null;
    private int limit;

    public ThreadWaitTest(int limit) {
        this.limit = limit;
        queue = new ArrayDeque<>(limit);
    }

    public synchronized void put(E e) throws InterruptedException {
        System.out.println(queue.toString());
        while (queue.size() == limit) {
            wait();
        }
        queue.add(e);
        notifyAll();
    }

    public synchronized E take() throws InterruptedException {
        System.out.println(queue.toString());
        while (queue.isEmpty()) {
            wait();
        }
        E e = queue.poll();
        notifyAll();
        return e;
    }

    public static void main(String[] args) {
        ThreadWaitTest<Integer> threadWaitTest = new ThreadWaitTest<Integer>(5);

        for (int i = 0; i < 10; i++) {
            PushThread pushThread = new PushThread("pushThread" + i, threadWaitTest);
            pushThread.start();
        }

        for (int i = 0; i < 1; i++) {
            PollThread pollThread = new PollThread("pollThread" + i, threadWaitTest);
            pollThread.start();
        }

        System.out.println("Main Stop");
    }

}

class PushThread extends Thread {
    private ThreadWaitTest threadWaitTest;

    public PushThread(@NotNull String name, ThreadWaitTest threadWaitTest) {
        super(name);
        this.threadWaitTest = threadWaitTest;
    }

    @Override
    public void run() {
        try {
            int num = 1;
            while (true) {
                System.out.println(Thread.currentThread().getName() + " start");
                this.threadWaitTest.put(num++);
                TimeUnit.SECONDS.sleep((int) (Math.random() * 100));
                System.out.println(Thread.currentThread().getName() + " stop");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class PollThread extends Thread {
    private ThreadWaitTest threadWaitTest;

    public PollThread(@NotNull String name, ThreadWaitTest threadWaitTest) {
        super(name);
        this.threadWaitTest = threadWaitTest;
    }

    @Override
    public void run() {
        try {
            int num = 1;
            while (true) {
                System.out.println(Thread.currentThread().getName() + " start");
                this.threadWaitTest.take();
                TimeUnit.SECONDS.sleep((int) (Math.random() * 10));
                System.out.println(Thread.currentThread().getName() + " stop");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

